//
// Created by ningjian on 18-6-2.
//

#include <cstring>
#include <netinet/in.h>
#include <iostream>
#include "RTPPackage.hpp"


unsigned long long ntohll(unsigned long long val) {
    if (__BYTE_ORDER == __LITTLE_ENDIAN) {
        return (((unsigned long long) htonl((int) ((val << 32) >> 32))) << 32) | (unsigned int) htonl((int) (val >> 32));
    } else if (__BYTE_ORDER == __BIG_ENDIAN) {
        return val;
    }
}

unsigned long long htonll(unsigned long long val) {
    if (__BYTE_ORDER == __LITTLE_ENDIAN) {
        return (((unsigned long long) htonl((int) ((val << 32) >> 32))) << 32) | (unsigned int) htonl((int) (val >> 32));
    } else if (__BYTE_ORDER == __BIG_ENDIAN) {
        return val;
    }
}


RTPPackage::RTPPackage() {

}

RTPPackage::~RTPPackage() {
    if (send_data != NULL) {
        delete[]send_data;
    }
}


uint8_t *RTPPackage::getSendData(size_t &out_len) {

    uint8_t vpxcc = (V << 6) + (P << 5) + (X << 4) + CC;

    uint8_t m_pt = (this->M << 7) + this->PT;

    uint8_t datatype_subpackageflag = (DataType << 4) + SubpackageFlag;

    size_t head_size = 30;
    if (DataType == A_F || DataType == T_T) {
        head_size -= 4;
    }

    send_len = head_size + Body_Len;

    send_data = new uint8_t[send_len];

    size_t offset = 0;
    memcpy(send_data, FH, 4);
    offset += 4;
    send_data[offset] = vpxcc;
    ++offset;
    send_data[offset] = m_pt;
    ++offset;

    uint16_t sn = htons(SN);
    memcpy(send_data + offset, &sn, 2);
    offset += 2;

    memcpy(send_data + offset, SIM, 6);
    offset += 6;

    send_data[offset] = CH;
    ++offset;

    send_data[offset] = datatype_subpackageflag;
    ++offset;

    uint64_t ts = htonll(TS);
    memcpy(send_data + offset, &ts, 8);
    offset += 8;

    if (DataType == A_F || DataType == T_T) {}
    else {
        uint16_t tmp = htons(Last_I_Frame_Interval);
        memcpy(send_data + offset, &tmp, 2);
        offset += 2;

        tmp = htons(Last_Frame_Interval);
        memcpy(send_data + offset, &tmp, 2);
        offset += 2;
    }

    uint16_t len = htons(Body_Len);
    memcpy(send_data + offset, &len, 2);
    offset += 2;

    memcpy(send_data + offset, Body_Data, Body_Len);

    out_len = send_len;
    return send_data;
}


void RTPPackage::GetRTPPackagesOnFrameData(std::list<RTPPackage *> &outs,
                                           uint16_t &sn,
                                           uint8_t sim[6],
                                           uint8_t ch,
                                           uint8_t pt,
                                           uint8_t dtype,
                                           uint64_t ts,
                                           size_t frame_len,
                                           uint8_t *frame_data,
                                           uint16_t last_I_I,
                                           uint16_t last_F_I) {
    RTPPackage* p_rtpp = NULL;
    size_t frame_data_offset = 0;
    size_t full_len_package_num = 0;
    size_t last_package_data_size = frame_len;
    //判断数据需要分包
    if (frame_len > 950) {
        full_len_package_num = frame_len / 950;
        last_package_data_size = frame_len % 950;
    }

    for(size_t i = 0 ; i < full_len_package_num; ++i){
        p_rtpp = new RTPPackage;

        p_rtpp->SN = sn;
        ++sn;

        memcpy(p_rtpp->SIM,sim,6);
        p_rtpp->CH = ch;
        p_rtpp->PT = pt;
        p_rtpp->DataType = dtype;
        p_rtpp->TS = ts;

        p_rtpp->Body_Data = frame_data + frame_data_offset;
        frame_data_offset += 950;
        p_rtpp->Body_Len = 950;

        if(i == 0) {
            p_rtpp->M = 1;
            p_rtpp->SubpackageFlag = SPF_FIRST;
        }
        else {
            p_rtpp->M = 0;
            p_rtpp->SubpackageFlag = SPF_MID;
        }

        outs.push_back(p_rtpp);
    }

    if(last_package_data_size != 0){
        // for last or atom
        p_rtpp = new RTPPackage;
        p_rtpp->SN = sn;
        ++sn;

        memcpy(p_rtpp->SIM,sim,6);
        p_rtpp->CH = ch;
        p_rtpp->PT = pt;
        p_rtpp->DataType = dtype;
        p_rtpp->TS = ts;

        p_rtpp->Body_Data = frame_data + frame_data_offset;
        p_rtpp->Body_Len = (uint16_t)last_package_data_size;
        if(full_len_package_num == 0) {
            p_rtpp->M = 1;
            p_rtpp->SubpackageFlag = SPF_ATOM;
        }
        else {
            p_rtpp->M = 1;
            p_rtpp->SubpackageFlag = SPF_LAST;
        }

        outs.push_back(p_rtpp);
    }

}